#include "App_485_Task.h"
#include "App_Modbus_Proto.h"
#include "board.h"
#include "log.h"
#include "system.h"
#include "usart-board.h"

#if defined(CONFIG_DTU_485)

int AppSerialCommunication(uint8_t cmd[], int len, uint8_t recv[])
{
    int i = 0;
    LOG_PRINTF(LL_DEBUG, "Serial Send:");
    for (i = 0; i < len; i++) {
        LOG_PRINTF(LL_DEBUG, "%02X ", cmd[i]);
    }
    LOG_PRINTF(LL_DEBUG, "\r\n");

    UsartFifoFlush(UART_INDEX_485);
    UartSendData(UART_INDEX_485, cmd, len);

    vTaskDelay(500);
    uint32_t start = RtcGetElapsedTime();
    int index = 0;

    while ((RtcGetElapsedTime() - start) < 1000) {
        uint8_t data = 0;
        if (UsartGetOneData(UART_INDEX_485, &data) == CL_OK) {
            recv[index++] = data;
        } else {
            vTaskDelay(100);
        }
        // LOG_PRINTF(LL_DEBUG, "App_485_Task:diff = %d\r\n", diff);
    }

    LOG_PRINTF(LL_DEBUG, "Serial Receive:");
    for (i = 0; i < index; i++) {
        LOG_PRINTF(LL_DEBUG, "%02X ", recv[i]);
    }
    LOG_PRINTF(LL_DEBUG, "\r\n");
    return index;
}

int AppSerialDebug(uint8_t* cmd, int len)
{
    uint8_t recv[64] = {0};
    int i = 0;
    /*
      打包协议-发送数据格式(8字节):从机地址1字节，功能码1字节，寄存器地址2字节，寄存器数量2字节，crc校验2字节
    */
    return AppSerialCommunication(cmd, len, recv);
}

int AppDeviceTask(LoraDevice_t* device, SystemAttributeData_t* proto, LoraModel_t* devModel, uint8_t out[])
{
    uint8_t recv[64] = {0};
    uint8_t cmd[64];
    uint8_t cmdLen = 0;

    for (int i = 0; i <= proto->attrCmdLen; i++) {
        if (i == proto->attrAddrOffset) {
            memcpy(&cmd[cmdLen], device->devAddr, device->addrLength);
            cmdLen += device->addrLength;
        } else if (i == proto->attrVerifyOffset) {
            if (proto->attrVerify == 1) {
                uint8_t chk = CheckSum(cmd, cmdLen);
                cmd[cmdLen++] = chk;
            } else {
                uint16_t crc = App_Crc16(cmd, cmdLen);
                cmd[cmdLen++] = ((crc >> 8) & 0xff);
                cmd[cmdLen++] = crc & 0xff;
            }
        } else if (i == proto->attrRegOffset) {
            memcpy(&cmd[cmdLen], devModel->regAddr, devModel->regLengh);
            cmdLen += devModel->regLengh;
        } else {
            if (i < proto->attrCmdLen) {
                cmd[cmdLen++] = proto->attrCmd[i];
            }
        }
    }

    int recvLen = AppSerialCommunication(cmd, cmdLen, recv);
    if (devModel->dataOffset < 0 || devModel->dataLen < 0 || recvLen < (devModel->dataLen + devModel->dataOffset)) {
        LOG_PRINTF(LL_DEBUG, "Serial 485:receve data not valid\r\n");
        return 0;
    }

    memcpy(out, &recv[devModel->dataOffset], devModel->dataLen);
    // SystemLoRaData.AttrSampleData[appModbusProto.attrId-1].attrData = (uint8_t)*(recv + 3 +
    // appModbusProto.resultOffset); SystemLoRaData.AttrSampleData[appModbusProto.attrId-1].attrState = ATTR_SET;
    LOG_PRINTF(LL_DEBUG, "receive acqType = %d, data len = %d\r\n", devModel->acqType, devModel->dataLen);
    return devModel->dataLen;
}

int AppSerialTask(LoraDevice_t* device, uint8_t out[])
{
    int length = 0;
    LoraDeviceModel_t* devModel = FindDeviceModel(device->modelId);
    if (devModel == NULL) {
        LOG_PRINTF(LL_DEBUG, "No this model, modelId = %d\r\n", device->modelId);
        return 0;
    }
    SystemAttributeData_t* proto = FindDeviceAttr(devModel->attrId);

    if (proto == NULL) {
        LOG_PRINTF(LL_DEBUG, "No this protocol, attrId = %d\r\n", devModel->attrId);
        return 0;
    }
    for (int i = 0; i < LORAMODEL_MAX_NUM; i++) {
        if (devModel->model[i].acqType == 0 || devModel->model[i].acqType & 0x80) {
            continue;
        }
        uint8_t result[8];
        int len = AppDeviceTask(device, proto, &devModel->model[i], result);
        if (len > 0) {
            Fill_Data_1B(out, &length, devModel->model[i].acqType);
            Fill_Data_1B(out, &length, len);
            Fill_Data(out, &length, result, len);
        }
    }
    return length;
}

void App_Data_Upload(LoraDevice_t* loraDevice)
{
    int index = 0;
    uint8_t out[64];
    uint8_t recv[32];
    int len = AppSerialTask(loraDevice, recv);
    if (len > 0) {
        // Fill_Data_1B(out, &index, proto->attrId);
        Fill_Data_1B(out, &index, len);
        Fill_Data(out, &index, recv, len);
    }
    if (index > 0) {
        App_Lora_Proto_SendData(out, index);
    }
}

void App_485_Task(void* pvParameters)
{
    LoraDevice_t loraDevice = {0};
    while (1) {
        if (xQueueReceive(SystemLoRaData.rs485TxQueue, &loraDevice, portMAX_DELAY) == pdPASS) {
            // for (int i = 0; i < SYSTEM_DEVICE_NUM; i++) {
            // LoraDevice_t* device = &SystemParmData.loraDevice[i];
            if (loraDevice.modelId == 0 || SystemLoRaData.rs485TxQueue == NULL || SystemLoRaData.loraTxMutex == NULL) {
                continue;
            }
            // LOG_PRINTF(LL_DEBUG, "Notify device acquire, index = %d\r\n", i);
            App_Data_Upload(&loraDevice);
            // }
        }
    }
}

#endif
